using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.SqlManagerUI;
using Microsoft.SqlServer.Management.SqlManagerUI.Scripting;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Globalization;
using System.IO;
using System.Net;
using System.Web.Services.Protocols;

namespace Microsoft.SqlServer.Tools.PublishWizard.CommandLine
{
	public class CommandLineManager
	{
		public enum ErrorCode
		{
			OperationCompletedSuccessfully,
			SyntaxErrorInvalidArguments,
			SourceDatabaseCannotBePublishedToParticularVersion,
			SourceDatabaseCannotBePublishedGivenOptions,
			SourceDatabaseCannotBeContacted,
			SourceDatabaseCredentialsAreInvalid,
			FileSpecifiedAlreadyExists,
			ErrorOccurredWhileScriptingDatabaseToFile,
			RemoteWebServiceCannotBeContacted,
			RemoteWebServiceCredentialsAreInvalid,
			RemoteSqlServerCannotBeContacted,
			RemoteSqlServerCredentialsAreInvalid,
			TimeoutOccurredWhilePublishing,
			SqlErrorHasOccurredDuringPublishing
		}

		private readonly string LOCALHOST_SERVER_NAME = "localhost";

		public int ParseAndExecuteArguments(string[] args)
		{
			if (args != null && args.Length > 0)
			{
				if (Parser.ParseHelp(args))
				{
					CommandLineManager.GenerateGeneralHelp();
				}
				else if (args[0].CompareTo(CommandLineResources.HelpVerb) == 0)
				{
					if (args.Length > 1)
					{
						if (args[1].CompareTo(CommandLineResources.ScriptVerb) == 0)
						{
							CommandLineParserBase commandLineParserBase = new ScriptCommandLineParser();
							CommandLineManager.ArgumentsUsage(typeof(ScriptCommandLineArguments), commandLineParserBase.Syntax);
						}
						else
						{
							if (args[1].CompareTo(CommandLineResources.PublishVerb) != 0)
							{
								CommandLineManager.ShowErrorMessage(string.Format(CultureInfo.CurrentCulture, CommandLineResources.UnRecognizedCommand, new object[]
								{
									args[1]
								}));
								return 1;
							}
							CommandLineParserBase commandLineParserBase = new PublishCommandLineParser();
							CommandLineManager.ArgumentsUsage(typeof(PublishCommandLineArguments), commandLineParserBase.Syntax);
						}
					}
					else
					{
						CommandLineManager.GenerateGeneralHelp();
					}
				}
				else if (args[0].CompareTo(CommandLineResources.ScriptVerb) == 0)
				{
					CommandLineParserBase commandLineParserBase = new ScriptCommandLineParser();
					CommandLineParserBase expr_E0 = commandLineParserBase;
					expr_E0.ErrorMessage = (EventHandler<MessageEventArgs>)Delegate.Combine(expr_E0.ErrorMessage, new EventHandler<MessageEventArgs>(this.ShowMessageEvent));
					ScriptCommandLineArguments scriptCommandLineArguments = new ScriptCommandLineArguments();
					if (!commandLineParserBase.Parse(args, scriptCommandLineArguments))
					{
						return 1;
					}
					this.DoScript(scriptCommandLineArguments);
				}
				else
				{
					if (args[0].CompareTo(CommandLineResources.PublishVerb) != 0)
					{
						CommandLineManager.ShowErrorMessage(string.Format(CultureInfo.CurrentCulture, CommandLineResources.FirstArgument, new object[0]));
						return 1;
					}
					CommandLineParserBase commandLineParserBase = new PublishCommandLineParser();
					CommandLineParserBase expr_133 = commandLineParserBase;
					expr_133.ErrorMessage = (EventHandler<MessageEventArgs>)Delegate.Combine(expr_133.ErrorMessage, new EventHandler<MessageEventArgs>(this.ShowMessageEvent));
					PublishCommandLineArguments publishCommandLineArguments = new PublishCommandLineArguments();
					if (!commandLineParserBase.Parse(args, publishCommandLineArguments))
					{
						return 1;
					}
					this.DoScript(publishCommandLineArguments);
				}
			}
			else
			{
				CommandLineManager.GenerateGeneralHelp();
			}
			return 0;
		}

		private int DoScript(CommonCommandLineArguments commandArguments)
		{
			int result;
			try
			{
				ScriptingDriver scriptingDriver;
				if (commandArguments.ConnectionString != null)
				{
					scriptingDriver = new ScriptingDriver(commandArguments.ConnectionString);
					SqlConnectionStringBuilder sqlConnectionStringBuilder = new SqlConnectionStringBuilder(commandArguments.ConnectionString);
					if (!string.IsNullOrEmpty(sqlConnectionStringBuilder.InitialCatalog))
					{
						scriptingDriver.DatabaseName = sqlConnectionStringBuilder.InitialCatalog;
					}
					else
					{
						if (string.IsNullOrEmpty(sqlConnectionStringBuilder.AttachDBFilename) || !sqlConnectionStringBuilder.UserInstance)
						{
							CommandLineManager.ShowErrorMessage(ScriptingEngineResources.ERROR_DatabaseNotPresentInConnectionString);
							result = 1;
							return result;
						}
						scriptingDriver.DatabaseName = sqlConnectionStringBuilder.AttachDBFilename;
					}
				}
				else
				{
					if (commandArguments.ServerName == null)
					{
						commandArguments.ServerName = this.LOCALHOST_SERVER_NAME;
					}
					if (commandArguments.UserName != null && commandArguments.Password != null)
					{
						scriptingDriver = new ScriptingDriver(commandArguments.LocalDatabaseName, commandArguments.ServerName, commandArguments.UserName, commandArguments.Password);
					}
					else
					{
						scriptingDriver = new ScriptingDriver(commandArguments.LocalDatabaseName, commandArguments.ServerName);
					}
				}
				if (scriptingDriver != null)
				{
					scriptingDriver.SchemaQualify = !commandArguments.NoSchemaQualify;
					scriptingDriver.SchemaOnly = commandArguments.SchemaOnly;
					scriptingDriver.DataOnly = commandArguments.DataOnly;
					scriptingDriver.DropExistingObjects = !commandArguments.NoDropExisting;
					if (commandArguments.TargetServer == CommandLineResources.SQLServerVersion2000)
					{
						scriptingDriver.TargetServerVersion = SqlServerVersion.Version80;
					}
					else if (commandArguments.TargetServer == CommandLineResources.SQLServerVersion2005)
					{
						scriptingDriver.TargetServerVersion = SqlServerVersion.Version90;
					}
					else
					{
						scriptingDriver.TargetServerVersion = SqlServerVersion.Version100;
					}
					bool suppressOutput = commandArguments.SuppressOutput;
					ScriptCommandLineArguments scriptCommandLineArguments = commandArguments as ScriptCommandLineArguments;

					if (scriptCommandLineArguments != null)
					{
                        if (scriptCommandLineArguments.IsFilePerObj)
                        {
                            scriptingDriver.Destination = ScriptDestination.FilePerObject;
                        }
                        else
                        {
                            scriptingDriver.Destination = ScriptDestination.SingleFile;
                        }
                        
						scriptingDriver.OverwriteExisting = scriptCommandLineArguments.OverrideExistingOutputFile;
						string outputPath = (string)scriptCommandLineArguments.Commands[1];
						scriptingDriver.OutputPath = outputPath;
					}
					else
					{
						PublishCommandLineArguments publishCommandLineArguments = commandArguments as PublishCommandLineArguments;
						if (publishCommandLineArguments != null)
						{
							scriptingDriver.Destination = ScriptDestination.PublishToWeb;
							scriptingDriver.UseTransactionForPublish = !publishCommandLineArguments.NoTransaction;
							if (!string.IsNullOrEmpty(publishCommandLineArguments.ProviderName) && !CommandLineManager.FindProviderInfo(publishCommandLineArguments.ProviderName, publishCommandLineArguments))
							{
								CommandLineManager.ShowErrorMessage(CommandLineResources.ERRORHosterNotFound);
								result = 1;
								return result;
							}
							if (!CommandLineManager.ValidateForPublish(publishCommandLineArguments))
							{
								result = 1;
								return result;
							}
							scriptingDriver.WebServiceAddress = publishCommandLineArguments.WebService;
							scriptingDriver.WebServiceSqlDatabaseName = publishCommandLineArguments.RemoteDatabaseName;
							scriptingDriver.WebServiceSqlPassword = publishCommandLineArguments.RemoteDatabasePassword;
							scriptingDriver.WebServiceSqlServerName = publishCommandLineArguments.RemoteServerName;
							scriptingDriver.WebServiceSqlUserName = publishCommandLineArguments.RemoteDatabaseUserName;
							scriptingDriver.WebServiceUserName = publishCommandLineArguments.WebServiceUserName;
							scriptingDriver.WebServicePassword = publishCommandLineArguments.WebServicePassword;
						}
					}
					if (!suppressOutput)
					{
						ScriptingDriver expr_252 = scriptingDriver;
						expr_252.ProgressEvent = (EventHandler<ProgressEventArgs>)Delegate.Combine(expr_252.ProgressEvent, new EventHandler<ProgressEventArgs>(this.ScriptProgressEvent));
					}
					Console.WriteLine(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.GeneratingScript, new object[]
					{
						scriptingDriver.DatabaseName
					}));
					if (scriptingDriver.SchemaOnly)
					{
						Console.WriteLine(ScriptingEngineResources.ChoseSchemaOnly);
					}
					else if (scriptingDriver.DataOnly)
					{
						Console.WriteLine(ScriptingEngineResources.ChoseDataOnly);
					}
					string text = string.Empty;
					switch (scriptingDriver.TargetServerVersion)
					{
					case SqlServerVersion.Version80:
						text = CommandLineResources.SQLServerVersion2000;
						break;
					case SqlServerVersion.Version90:
						text = CommandLineResources.SQLServerVersion2005;
						break;
					case SqlServerVersion.Version100:
						text = CommandLineResources.SQLServerVersion2008;
						break;
					}
					Console.WriteLine(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ChoseTargetServerVersion, new object[]
					{
						text
					}));
					scriptingDriver.GenerateScript();
					result = 0;
				}
				else
				{
					result = 7;
				}
			}
			catch (SqlException ex)
			{
				CommandLineManager.ShowErrorMessage(CommandLineResources.Sqlclient, ex);
				result = 7;
			}
			catch (ConnectionFailureException ex2)
			{
				CommandLineManager.ShowErrorMessage(CommandLineResources.Sqlclient, ex2.InnerException);
				result = 4;
			}
			catch (FileNotFoundException ex3)
			{
				CommandLineManager.ShowErrorMessage(ex3.Message);
				if (string.Compare(ex3.Message, ScriptingEngineResources.ERROR_FileExists, StringComparison.CurrentCulture) == 0)
				{
					result = 6;
				}
				else
				{
					result = 7;
				}
			}
			catch (DirectoryNotFoundException ex4)
			{
				CommandLineManager.ShowErrorMessage(CommandLineResources.ERROR_DirectoryNotFound, ex4);
				result = 7;
			}
			catch (UnsupportedFeatureException ex5)
			{
				CommandLineManager.ShowErrorMessage(ex5.Message);
				result = 3;
			}
			catch (IOException ex6)
			{
				CommandLineManager.ShowErrorMessage(ex6.Message);
				result = 6;
			}
			catch (NonSupportedCollationException ex7)
			{
				CommandLineManager.ShowErrorMessage(ex7.Message);
				result = 2;
			}
			catch (UnsupportedVersionException ex8)
			{
				CommandLineManager.ShowErrorMessage(ex8.Message);
				result = 2;
			}
			catch (WebException ex9)
			{
				if (ex9.Response is HttpWebResponse)
				{
					HttpWebResponse httpWebResponse = ex9.Response as HttpWebResponse;
					HttpStatusCode statusCode = httpWebResponse.StatusCode;
					if (statusCode == HttpStatusCode.Unauthorized)
					{
						CommandLineManager.ShowErrorMessage(ScriptingEngineResources.ERROR_InvalidWebServiceLogin);
						result = 9;
						return result;
					}
					if (statusCode == HttpStatusCode.NotFound)
					{
						CommandLineManager.ShowErrorMessage(string.Format(GenScriptWizSR.TestFailureMessage, httpWebResponse.ResponseUri, CultureInfo.CurrentCulture));
						result = 8;
						return result;
					}
				}
				CommandLineManager.ShowErrorMessage(ex9.Message);
				result = 8;
			}
			catch (SoapException ex10)
			{
				CommandLineManager.ShowErrorMessage(ex10.Message);
				string a;
				if ((a = CommandLineManager.InspectExceptionDetailForError(ex10)) != null)
				{
					if (a == "PublishTimeoutException")
					{
						result = 12;
						return result;
					}
					if (a == "SqlErrorException")
					{
						result = 13;
						return result;
					}
				}
				result = 13;
			}
			catch (Exception ex11)
			{
				CommandLineManager.ShowErrorMessage(ex11.Message);
				throw;
			}
			return result;
		}

		private static string InspectExceptionDetailForError(SoapException se)
		{
			return se.Detail.ChildNodes[0].Attributes["type"].Value;
		}

		private static bool FindProviderInfo(string hosterName, PublishCommandLineArguments publishCommandArguments)
		{
			bool result = false;
			ProviderCollection providerCollection = HostingConfigurationManager.LoadProvidersFromDisk();
			foreach (ProviderEntity current in providerCollection)
			{
				if (string.Compare(current.Name, hosterName, StringComparison.CurrentCulture) == 0)
				{
					if (string.IsNullOrEmpty(publishCommandArguments.WebService))
					{
						publishCommandArguments.WebService = current.WebServiceAddress;
					}
					if (string.IsNullOrEmpty(publishCommandArguments.WebServiceUserName))
					{
						publishCommandArguments.WebServiceUserName = current.UserName;
					}
					if (string.IsNullOrEmpty(publishCommandArguments.WebServicePassword))
					{
						publishCommandArguments.WebServicePassword = current.Password;
					}
					foreach (DatabaseEntity current2 in current.Databases)
					{
						if (current2.IsDefault)
						{
							if (string.IsNullOrEmpty(publishCommandArguments.RemoteDatabaseUserName))
							{
								publishCommandArguments.RemoteDatabaseName = current2.DatabaseName;
							}
							if (string.IsNullOrEmpty(publishCommandArguments.RemoteServerName))
							{
								publishCommandArguments.RemoteServerName = current2.ServerName;
							}
							if (string.IsNullOrEmpty(publishCommandArguments.RemoteDatabaseUserName))
							{
								publishCommandArguments.RemoteDatabaseUserName = current2.UserName;
							}
							if (string.IsNullOrEmpty(publishCommandArguments.RemoteDatabasePassword))
							{
								publishCommandArguments.RemoteDatabasePassword = current2.Password;
								break;
							}
							break;
						}
					}
					result = true;
					break;
				}
			}
			return result;
		}

		private void ScriptProgressEvent(object sender, ProgressEventArgs e)
		{
			ProgressEventType eventType = e.EventType;
			if (eventType == ProgressEventType.Reporting)
			{
				Console.Write(e.Status);
				return;
			}
			Console.WriteLine(e.Status);
		}

		private void ShowMessageEvent(object sender, MessageEventArgs e)
		{
			CommandLineManager.ShowErrorMessage(e.Message);
		}

		private static void ShowErrorMessage(string resourceValue, Exception ex)
		{
			string value = string.Empty;
			if (ex != null)
			{
				value = string.Format(CultureInfo.CurrentCulture, CommandLineResources.ERROR_FormatWithException, new object[]
				{
					resourceValue,
					ex.Message
				});
			}
			else
			{
				value = string.Format(CultureInfo.CurrentCulture, CommandLineResources.ERROR_Format, new object[]
				{
					resourceValue
				});
			}
			Console.WriteLine(value);
		}

		private static bool ValidateForPublish(PublishCommandLineArguments publishCommandArguments)
		{
			bool result = false;
			if (string.IsNullOrEmpty(publishCommandArguments.WebService))
			{
				CommandLineManager.ShowErrorMessage(CommandLineResources.ERROR_WebServiceAddIsNull);
			}
			else if (string.IsNullOrEmpty(publishCommandArguments.WebServiceUserName))
			{
				CommandLineManager.ShowErrorMessage(CommandLineResources.ERROR_WebServiceUsernameIsNull);
			}
			else if (string.IsNullOrEmpty(publishCommandArguments.WebServicePassword))
			{
				CommandLineManager.ShowErrorMessage(CommandLineResources.ERROR_WebServicePasswordIsNull);
			}
			else if (string.IsNullOrEmpty(publishCommandArguments.RemoteServerName))
			{
				CommandLineManager.ShowErrorMessage(CommandLineResources.ERROR_RemoteServerNameIsNull);
			}
			else if (string.IsNullOrEmpty(publishCommandArguments.RemoteDatabaseName))
			{
				CommandLineManager.ShowErrorMessage(CommandLineResources.ERROR_RemoteDatabaseNameIsNull);
			}
			else if (string.IsNullOrEmpty(publishCommandArguments.RemoteDatabaseUserName))
			{
				CommandLineManager.ShowErrorMessage(CommandLineResources.ERROR_RemoteUsernameIsNull);
			}
			else if (string.IsNullOrEmpty(publishCommandArguments.RemoteDatabasePassword))
			{
				CommandLineManager.ShowErrorMessage(CommandLineResources.ERROR_RemotePasswordIsNull);
			}
			else
			{
				result = true;
			}
			return result;
		}

		private static void ShowErrorMessage(string resourceValue)
		{
			CommandLineManager.ShowErrorMessage(resourceValue, null);
		}

		private static void GenerateGeneralHelp()
		{
			Console.WriteLine(Parser.ArgumentsUsage(null, new List<string>
			{
				new ScriptCommandLineParser().Syntax,
				new PublishCommandLineParser().Syntax
			}));
			Console.WriteLine(CommandLineResources.ForMoreInfo + "\n");
			Console.WriteLine(string.Concat(new string[]
			{
				"\t",
				CommandLineResources.CmdExeName,
				" ",
				CommandLineResources.HelpVerb,
				" ",
				CommandLineResources.ScriptVerb
			}));
			Console.WriteLine(string.Concat(new string[]
			{
				"\t",
				CommandLineResources.CmdExeName,
				" ",
				CommandLineResources.HelpVerb,
				" ",
				CommandLineResources.PublishVerb,
				"\n"
			}));
			Console.WriteLine(CommandLineResources.HomePage);
		}

		public static void ArgumentsUsage(Type type, string syntax)
		{
			Console.WriteLine(Parser.ArgumentsUsage(type, syntax));
		}
	}
}
